<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 1、定义一个被代理的数据，模拟组件中data数据选项
        let user = { name: '李四', age: 20 };

        // 2、定义代理对象  Object.defineProperty() 模拟组件实例本身vueComponent
        // 语法：Object.defineProperty(代理对象, 属性, 描述)
        // 被代理的数据层级如果比较深，需要循环递归实现数据代理
        // 从被代理user对象中依次取出需要代理的数据，挂载到代理对象vm上
        let vm = {}; // 代理对象

        // Object.defineProperty(vm, "name", {
        //     //name属性被设置时触发
        //     set(value) { //value：修改的值
        //         console.log("name属性被赋值了");
        //         user.name = value;
        //     },
        //     //name属性被获取时触发
        //     get() {
        //         console.log("name属性被获取了");
        //         return user.name;
        //     }
        // });

        // //3.获取和设置属性的值
        // console.log(vm.name); //name属性被获取了   李四
        // vm.name = "妲己"

        //4.问题一：监听属性，如果有多个属性，就需要循环，如果层级复杂，还需要递归
        for (let attr in user) {
            Object.defineProperty(vm, attr, {
                //允许删除属性
                configurable:true,

                //name属性被设置时触发
                set(value) { //value：修改的值
                    console.log(attr+"属性被赋值了");
                    user[attr] = value;
                },

                //name属性被获取时触发
                get() {
                    console.log(attr + "属性被获取了");
                    return user[attr];
                }
            });
        }

        //监听了两个，vm下面有age，name，都有对应的get和set方法，数据发生变化就能监听到，实现响应式
        console.log(vm);
        console.log(vm.name); //name属性被获取了
        console.log(vm.age); //age属性被获取了


        //4.问题二：后期添加属性，没有get和set方法，因此不会有响应式 ，$set 
        vm.haha = "今天星期四，真开心！";


        //5.问题三：删除某个属性不会触发set和get方法, $delete
        // configurable:true, 注意添加这个属性才能删除
        delete vm.name;
        console.log(vm);

    </script>
</body>

</html>